@file:Suppress("MemberVisibilityCanBePrivate")

package com.virtualightning.mvvm.tools

import android.util.LruCache
import java.lang.ref.Reference
import java.lang.ref.ReferenceQueue
import java.lang.ref.SoftReference
import java.lang.ref.WeakReference

/**
 *  Anchor : Create by CimZzz
 *  Time : 2021/3/16 11:11:57
 *  Project : zxs-new
 *  数据缓存池
 */
class DataCache<T, E>(maxSize: Int) {
    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/3/16 上午11:12
    // 内部最小使用池
    ///////////////////////////////////////////////////////////////////////////
    private val lruCache = LruCache<Any, Reference<E>>(maxSize)

    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/3/16 上午11:13
    // 引用队列
    ///////////////////////////////////////////////////////////////////////////
    private val referenceQueue = ReferenceQueue<E>()

    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/3/16 上午11:16
    // 运算符重载，[]
    ///////////////////////////////////////////////////////////////////////////
    operator fun get(key: T): E? {
        evictCache()
        return lruCache.get(key)?.get()
    }

    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/3/16 上午11:31
    // 运算符重载，[]=
    ///////////////////////////////////////////////////////////////////////////
    operator fun set(key: T, any: E?) {
        evictCache()
        if(any == null) {
            remove(key)
        }
        else {
            lruCache.put(key, InnerReference(key as Any, any, referenceQueue))
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/3/16 上午11:31
    // 移除数据
    ///////////////////////////////////////////////////////////////////////////
    fun remove(key: T) {
        evictCache()
        lruCache.remove(key)
    }

    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/3/16 上午11:38
    // 回收全部数据
    ///////////////////////////////////////////////////////////////////////////
    fun clear() {
        lruCache.evictAll()
    }

    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/3/16 上午11:20
    // 将被移除引用的数据从缓存中移除
    ///////////////////////////////////////////////////////////////////////////
    private fun evictCache() {
        do {
            val reference = referenceQueue.poll() ?: break
            val innerRef = reference as? InnerReference<*> ?: continue
            lruCache.remove(innerRef.key)
        } while (true)
    }


    ///////////////////////////////////////////////////////////////////////////
    // 代码分割线 on 2021/3/16 上午11:16 by CimZzz
    // 以下内容为:
    // 内部类
    ///////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////////
    // Add by CimZzz on 2021/3/16 上午11:27
    // 内部引用
    ///////////////////////////////////////////////////////////////////////////
    private class InnerReference<E>(internal val key: Any, referent: E, queue: ReferenceQueue<E>)
        : WeakReference<E>(referent, queue) {
        /// 内部软引用持有
        private val softReference = SoftReference<E>(referent)
    }
}